package org.micode.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.micode.common.exception.RemoteServiceException;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.lang.reflect.Type;

@Slf4j
public class HttpUtils {

    private static RestTemplate restTemplate;

    static {
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();

        httpRequestFactory.setConnectionRequestTimeout(10000);
        httpRequestFactory.setConnectTimeout(10000);
        httpRequestFactory.setReadTimeout(10000);

        restTemplate = new RestTemplate(httpRequestFactory);
    }

    /**
     * POST请求
     */
    public static <T> T post(String url, Object data, Type returnType) {
        return request(url, data, returnType, HttpMethod.POST, null);
    }

    /**
     * POST请求
     */
    public static <T> T post(String url, Object data, Type returnType, HttpHeaders requestHeaders) {
        return request(url, data, returnType, HttpMethod.POST, requestHeaders);
    }

    /**
     * GET请求
     */
    public static <T> T get(String url, Object data, Type returnType) {
        return request(url, data, returnType, HttpMethod.GET, null);
    }

    /**
     * GET请求
     */
    public static <T> T get(String url, Object data, Type returnType, HttpHeaders requestHeaders) {
        return request(url, data, returnType, HttpMethod.GET, requestHeaders);
    }

    /**
     * 请求
     */
    public static <T> T request(String requestUrl,
                                Object data,
                                Type returnType,
                                HttpMethod httpMethod,
                                HttpHeaders requestHeaders) {
        try {
            if (log.isDebugEnabled()) {
                log.debug("Call the remote service: " + requestUrl + "," + data);
            }

            HttpEntity<?> httpEntity = new HttpEntity<>(data, requestHeaders);
            ResponseEntity<T> responseEntity = restTemplate.exchange(
                    requestUrl, httpMethod, httpEntity,
                    ParameterizedTypeReference.forType(returnType));
            T apiResult = responseEntity.getBody();
            if (log.isDebugEnabled()) {
                log.debug("The result of remote service: \n requestUrl: {}  \n result: {}", requestUrl, apiResult);
            }
            return apiResult;
        } catch (Exception e) {
            log.warn("Call the remote service({}) failed!", requestUrl, e);
            throw new RemoteServiceException("Call the remote service failed");
        }
    }

}
